package com.lab.util;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.List;

import org.springframework.beans.BeanUtils;

public class EntityUtils {

    /**
     * @param srcInstance 
     *          the source instance.
     * @param ignoreProperties.
     * @return new instance.
     */
    private static <T> T duplicate(T srcInstance, String... ignoreProperties) {
        Class<T> clazz = (Class<T>) srcInstance.getClass();

        T newInstance = null;
        try {
            newInstance = clazz.newInstance();
        } catch (InstantiationException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        }

        BeanUtils.copyProperties(srcInstance, newInstance, ignoreProperties);

        return newInstance;
    }

    /**
     * @param <T>
     * @param t1
     *          instance t1.
     * @param t2
     *          instance t2.
     * @return
     *          new instance.
     */
    public static <T> T merge(T t1, T t2) {
        T copied = duplicate(t1);

        List<Method> getters = ReflectionUtils.getGetters((Class<T>) t2
                .getClass());
        List<Method> setters = ReflectionUtils.getSetters((Class<T>) copied
                .getClass());

        for (Method _getter : getters) {
            try {
                Object returnValue = _getter.invoke(t2);
                if (returnValue != null) {
                    for (Method _setter : setters) {
                        if (matchName(_getter, _setter)) {
                            _setter.invoke(copied, returnValue);
                        }
                    }
                }
            } catch (IllegalArgumentException e) {
                e.printStackTrace();
            } catch (IllegalAccessException e) {
                e.printStackTrace();
            } catch (InvocationTargetException e) {
                e.printStackTrace();
            }
        }

        return copied;
    }

    private static boolean matchName(Method _getter, Method _setter) {
        return _getter.getName().substring(3).equals(
                _setter.getName().substring(3));
    }

}
